import 'dart:async';

import 'package:flustars/flustars.dart';

class CommonUtils {
  // 防抖函数: eg:输入框连续输入，用户停止操作300ms才执行访问接口
  static const deFaultDurationTime = 300;
  static Timer? timer;

  static antiShake(Function doSomething, {durationTime = deFaultDurationTime}) {
    timer?.cancel();
    timer = Timer(Duration(milliseconds: durationTime), () {
      doSomething.call();
      timer = null;
    });
  }

  // 节流函数: eg:300ms内，只会触发一次
  static int startTime = 0;

  static throttle(Function doSomething, {durationTime = deFaultDurationTime}) {
    int currentTime = DateTime.now().millisecondsSinceEpoch;
    if (currentTime - startTime > durationTime) {
      doSomething.call();
      startTime = DateTime.now().millisecondsSinceEpoch;
    }
  }

  // 根据身份证号计算 年龄
  static int getAgeWithIDCard(String idCard) {
    int age = 0;
    if (RegexUtil.isIDCard(idCard)) {
      int? year = int.tryParse(idCard.substring(6, 10));
      int now = DateTime.now().year;
      return now - year!;
    }
    return age;
  }

  // 根据身份证号计算出生日期
  static String getBirthdayDCard(String idCard) {
    if (idCard == "" || idCard.length < 16) {
      return "";
    }
    return idCard.substring(6, 14);
  }

  //根据生日计算年龄
  static String getAgeByBirthday(String birthday) {
    int age = 0;
    if (birthday != "") {
      DateTime? birth = DateTime.tryParse(birthday);
      int now = DateTime.now().year;
      DateTime? d = birth ?? DateTime.now();
      age = (now - d.year);
    }
    return "$age岁";
  }

  static String getFormatedDateTime(String dt) {
    List<String> mList = dt.split(" ");
    List<String> d = mList[0].split("/");
    List<String> t = mList[1].split(":");
    return "${d[0]}-${d[1].length == 1 ? "0${d[1]}" : d[1]}-${d[2].length == 1 ? "0${d[2]}" : d[2]} ${t[0].length == 1 ? "0${t[0]}" : t[0]}${t[1].length == 1 ? "0" + t[1] : t[1]}${t[2].length == 1 ? "0" + t[2] : t[2]}";
  }

  //当前月份天数
  static int getMouthDays(int year, int month) {
    int days = 0;
    if (month != 2) {
      switch (month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
          days = 31;
          break;
        case 4:
        case 6:
        case 9:
        case 11:
          days = 30;
          break;
      }
    } else {
      // 闰年
      if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
        days = 29;
      } else {
        days = 28;
      }
    }
    return days;
  }

  /// 获取性别
  static bool? isManFromIdCard(String idCard) {
    if (RegexUtil.isIDCard(idCard)) {
      var value = idCard.substring(16, 17);
      return int.parse(value) % 2 == 0 ? false : true;
    } else {
      return null;
    }
  }

  /// 安全取出map值(String)
  static String safeGetMap(item, key, {placehoder = ''}) {
    if (item == null || item.isEmpty) return placehoder;
    var value = item[key];
    if (value == null || value.toString().isEmpty || value == 'null') {
      return placehoder;
    }
    return value.toString();
  }

  // 15位转18位身份证号
  static String get18Ic(String identityCard) {
    String retId = "";
    String id17 = "";
    int? sum = 0;
    int y = 0;
    // 定义数组存放加权因子（weight factor）
    List wf = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
    // 定义数组存放校验码（check code）
    List cc = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"];
    // 加上两位年19
    id17 = "${identityCard.substring(0, 6)}19${identityCard.substring(6)}";
    // 十七位数字本体码加权求和
    for (int i = 0; i < 17; i++) {
      sum = (sum! + int.parse(id17.substring(i, i + 1)) * wf[i]) as int?;
    }
    // 计算模
    y = (sum! % 11);
    // 通过模得到对应的校验码 cc[y]
    retId = id17 + cc[y];
    return retId;
  }

  /// 判断是否是身份证号
  static bool isCardId(String cardId) {
    if (cardId.length == 15) {
      cardId = get18Ic(cardId);
    } else if (cardId.length > 15 && cardId.length < 18) {
      cardId = cardId.trim();
      if (cardId.length == 15) {
        cardId = get18Ic(cardId);
      }
    }
    if (cardId.length != 18) {
      return false; // 位数不够
    }
    // 身份证号码正则
    RegExp postalCode = RegExp(
        r'^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|[Xx])$');

    // 通过验证，说明格式正确，但仍需计算准确性
    if (!postalCode.hasMatch(cardId)) {
      return false;
    }
    //将前17位加权因子保存在数组里
    final List idCardList = [
      "7",
      "9",
      "10",
      "5",
      "8",
      "4",
      "2",
      "1",
      "6",
      "3",
      "7",
      "9",
      "10",
      "5",
      "8",
      "4",
      "2"
    ];
    //这是除以11后，可能产生的11位余数、验证码，也保存成数组
    final List idCardYArray = [
      '1',
      '0',
      '10',
      '9',
      '8',
      '7',
      '6',
      '5',
      '4',
      '3',
      '2'
    ];
    // 前17位各自乖以加权因子后的总和
    int idCardWiSum = 0;

    for (int i = 0; i < 17; i++) {
      int subStrIndex = int.parse(cardId.substring(i, i + 1));
      int idCardWiIndex = int.parse(idCardList[i]);
      idCardWiSum += subStrIndex * idCardWiIndex;
    }
    // 计算出校验码所在数组的位置
    int idCardMod = idCardWiSum % 11;
    // 得到最后一位号码
    String idCardLast = cardId.substring(17, 18);
    //如果等于2，则说明校验码是10，身份证号码最后一位应该是X
    if (idCardMod == 2) {
      if (idCardLast != 'x' && idCardLast != 'X') {
        return false;
      }
    } else {
      //用计算出的验证码与最后一位身份证号码匹配，如果一致，说明通过，否则是无效的身份证号码
      if (idCardLast != idCardYArray[idCardMod]) {
        return false;
      }
    }
    return true;
  }

  static String secToTime(times) {
    String result = '00:00:00';
    result = DateUtil.formatDate(
        DateTime.fromMillisecondsSinceEpoch(times, isUtc: true),
        format: DateFormats.h_m_s);
    return result;
  }

  static bool isPhone(String phoneNum) {
    RegExp exp = RegExp(
        r'^((13[0-9])|(14[0-9])|(15[0-9])|(16[0-9])|(17[0-9])|(18[0-9])|(19[0-9]))\d{8}$');
    //bool matched = exp.hasMatch(phoneNum);
    // RegExp ex = RegExp(r'^(0\d{2,3}\-)?([2-9]\d{6,7})+(\-\d{1,6})?$');
    // return exp.hasMatch(phoneNum) || ex.hasMatch(phoneNum);
    return exp.hasMatch(phoneNum);
  }


  //判断是否是为空字符串或者是null
  static bool isEmptyOrNull(String? str) {
    if (str==null ||  str.isEmpty|| str=="0"||  str.toUpperCase() == "NULL") {
      return true;
    }
    return false;
  }

  static String formatNum(double num, int position) {
    if ((num.toString().length - num.toString().lastIndexOf(".") - 1) <
        position) {
      //小数点后有几位小数
      return num.toStringAsFixed(position)
          .substring(0, num.toString().lastIndexOf(".") + position + 1)
          .toString();
    } else {
      return num.toString()
          .substring(0, num.toString().lastIndexOf(".") + position + 1)
          .toString();
    }
  }
}
